package com.pimee.common.config;

import java.io.IOException;
import java.math.BigDecimal;

import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.lang.reflect.Type;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;

@Configuration
public class JacksonConfig {

	/**
	 * Jackson全局转化long类型为String，解决jackson序列化时long类型缺失精度问题
	 * 
	 * @return Jackson2ObjectMapperBuilderCustomizer 注入的对象
	 */
	@Bean
	public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
		Jackson2ObjectMapperBuilderCustomizer cunstomizer = new Jackson2ObjectMapperBuilderCustomizer() {

			@Override
			public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
				jacksonObjectMapperBuilder.serializerByType(Long.TYPE, ToStringSerializer.instance);
				jacksonObjectMapperBuilder.serializerByType(Long.class, ToStringSerializer.instance);
				jacksonObjectMapperBuilder.serializerByType(BigDecimal.class, BigDecimalToStringSerializer.instance);
			}
		};

		return cunstomizer;
	}

	@SuppressWarnings("serial")
	@JacksonStdImpl
	static class BigDecimalToStringSerializer extends ToStringSerializer {
		public final static BigDecimalToStringSerializer instance = new BigDecimalToStringSerializer();

		public BigDecimalToStringSerializer() {
			super(Object.class);
		}

		public BigDecimalToStringSerializer(Class<?> handledType) {
			super(handledType);
		}

		@Override
		public boolean isEmpty(SerializerProvider prov, Object value) {
			if (value == null) {
				return true;
			}
			String str = ((BigDecimal) value).stripTrailingZeros().toPlainString();
			return str.isEmpty();
		}

		@Override
		public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
			gen.writeString(((BigDecimal) value).stripTrailingZeros().toPlainString());
		}
		
		@Override
		public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException {
			return createSchemaNode("string", true);
		}

		@Override
		public void serializeWithType(Object value, JsonGenerator gen, SerializerProvider provider,
				TypeSerializer typeSer) throws IOException {
			// no type info, just regular serialization
			serialize(value, gen, provider);
		}
	}
}